package com.workManager.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.workManager.exception.BusinessException;
import com.workManager.mapper.TbDirectEstimateMapper;
import com.workManager.mapper.TbDirectExpensesMapper;
import com.workManager.pojo.TbDirectExpenses;
import com.workManager.pojo.TbParameter;
import com.workManager.pojo.TbParameterType;
import com.workManager.pojo.TbProject;
import com.workManager.util.DateUtil;
import com.workManager.util.ExcelReadUtil;
import com.workManager.vo.DirectExpensesVo;
import com.workManager.vo.ProjectVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by worso on 2017/3/21 0021.
 */
@Service
public class DirectExpensesServiceImpl implements DirectExpensesService {

    @Autowired
    private TbDirectExpensesMapper directExpensesMapper;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private ParameterService parameterService;

    @Autowired
    private TbDirectEstimateMapper directEstimateMapper;

    public PageInfo<DirectExpensesVo> query(Map queryParam) {
        int pageno = !queryParam.containsKey("pagenum")||queryParam.get("pagenum")==null?1:Integer.parseInt(queryParam.get("pagenum").toString());
        int pagesize = !queryParam.containsKey("pagesize")||queryParam.get("pagesize")==null?10:Integer.parseInt(queryParam.get("pagesize").toString());
        PageHelper.startPage(pageno,pagesize);
        List<DirectExpensesVo> directExpensesVoList = directExpensesMapper.query(queryParam);
        PageInfo<DirectExpensesVo> pageInfo = new PageInfo<DirectExpensesVo>(directExpensesVoList);
        return pageInfo;
    }

    @Transactional
    public void uploadExcel(String name , MultipartFile file) throws  Exception{
        //读取Excel表格数据
        List<String[]> fileData = ExcelReadUtil.excelToList(name,file.getInputStream());


        String[] tableHead = fileData.get(0);

        String[] headTitle = {"年份","月份","项目编号及名称"};
        for (int i=0;i<headTitle.length;i++){
            String  headItem = tableHead[i].trim();
            if(!headItem.equals(headTitle[i])){
                throw  new BusinessException("表格格式不正确！请参考直接费用导入模板重新上传。(行：1，列："+(i+1)+")");
            }
        }

        //获取系统定义的直接费用类别列表
        List<TbParameterType> directExpensesCategoryList =  parameterService.getChildrenByName("直接费用类别");
        if(directExpensesCategoryList.size() == 0){
            throw  new BusinessException("上传失败，系统未定义直接费用类别");
        }

        /*//获取直接费用类别名称与ID键值对
        Map<String,Integer> directExpensesCategoryMap = parameterService.getNameAndIdMapByParameterTypes(directExpensesCategoryList);*/

        //获取直接费用类别ID列表
        List<Integer> directExpensesCategoryIdList = parameterService.getParamTypeIdByList(directExpensesCategoryList);

        //获取系统定义的直接费用类型列表
        List<TbParameter> directExpensesTypeList = parameterService.getParametersByParamTypeIds(directExpensesCategoryIdList);

        //获取直接费用类型名称与ID键值对
        Map<String,Integer> directExpensesTypeMap = parameterService.getNameAndIdMapByParameters(directExpensesTypeList);

        //获取直接费用类型名称列表
        List<String> directExpensesTypeNameList = parameterService.getParameterNames(directExpensesTypeList);

        //检查上传文件的直接费用类型是否正确
        String[] directExpensesTypeNames = Arrays.copyOfRange(tableHead, 3, tableHead.length);
        List<String> list = Arrays.asList(directExpensesTypeNames);
        List<String> arrayList = new ArrayList<String>(list);
        arrayList.removeAll(directExpensesTypeNameList);
        if(arrayList.size() > 0){
            throw  new BusinessException("上传失败，系统未定义费用科目：" + Arrays.toString(arrayList.toArray()));
        }

        //获取系统定义的项目列表
        //List<TbProject> projectList = projectService.getAllProjects();

        //获取项目名称与ID键值对
        //Map<String,Integer> projectMap = projectService.getNameAndIdMapByProjects(projectList);

        List<TbDirectExpenses> newDirectExpensesList = new ArrayList<TbDirectExpenses>();

        Date createDate = new Date();
        StringBuilder stringBuilder = new StringBuilder();

        //匹配金额
        String reg = "^-?[0-9]{1,8}(.[0-9]{1,2})?$";

        Map<String, Object> conditionmMap = new HashMap<String, Object>();
        String[] firstData = fileData.get(1);
        //设置费用发生为指定月份的最后一天
        int costYear = Integer.parseInt(firstData[0]);
        int costMonth = Integer.parseInt(firstData[1]);
        Date firstDay = DateUtil.getFirstDayOfMonth(costYear, costMonth);
        Date lastDay = DateUtil.getLastDayOfMonth(costYear, costMonth);
        conditionmMap.put("startTime", firstDay);
        conditionmMap.put("endTime", lastDay);


        Set<String> monthSet = new HashSet<>();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM");

        //读取文件行数据
        for(int i=1;i<fileData.size();i++){
            String[] rowData = fileData.get(i);

            //检查是否空行
            if(ExcelReadUtil.isBlankRow(rowData)){
                continue;
            }

            //检查项目是否正确
            String project = rowData[2].trim();
            Map<String,Object> map = new HashMap<>();
            map.put("codeName",project);
            ProjectVo vo = projectService.queryByCodeName(map);
            if(null == vo){
                stringBuilder.append("上传失败，系统未定义项目：" + project+"(行："+(i+1)+"，列：3)")
                        .append(System.getProperty("line.separator"));
                continue;
            }else if(vo.getProjectStatusName()!=null&&vo.getProjectStatusName().equals("已完结")){
                stringBuilder.append("项目：" + project + " 已完结！(行：" + (i+1) + "，列：3)")
                        .append(System.getProperty("line.separator"));
            }else if(vo.getProjectStatusName()!=null&&vo.getProjectStatusName().equals("已终结")){
                stringBuilder.append("项目：" + project + " 已终结！(行：" + (i+1) + "，列：3)")
                        .append(System.getProperty("line.separator"));
            }

            for(int j=3; j<rowData.length; j++){
                TbDirectExpenses directExpenses = new TbDirectExpenses();
                directExpenses.setProjectId(vo.getProjectId());
                directExpenses.setCostType(directExpensesTypeMap.get(tableHead[j]));

                String costAmount = rowData[j];
                if ("".equals(costAmount)){
                    continue;
                }
                if(costAmount.length() > 0 && costAmount.matches(reg)){
                    directExpenses.setCostAmount(new BigDecimal(costAmount));
                }else if(costAmount.length() > 0){
                    stringBuilder.append("金额请精确到小数点后2位，整数位不大于8位(行："+(i+1)+"，列："+(j+1)+")")
                            .append(System.getProperty("line.separator"));
                }

                directExpenses.setCostDate(lastDay);
                directExpenses.setCreateDate(createDate);
                directExpenses.setIsValid(true);

                newDirectExpensesList.add(directExpenses);
                //记录录入年月
                monthSet.add(sf.format(directExpenses.getCostDate()));
            }

        }

        if(stringBuilder.length() > 0){
            throw new BusinessException(stringBuilder.toString());
        }

        directExpensesMapper.deleteByConditions(conditionmMap);

        if(newDirectExpensesList.size() > 0 ){
            directExpensesMapper.batchInsert(newDirectExpensesList);
        }

        //报废预计表
        Map param = new HashMap();
        param.put("salMonths",monthSet);
        directEstimateMapper.invalid(param);

    }

}
